<?php
// +----------------------------------------------------------------------
// | sfadmin - Suifeng Administration
// +----------------------------------------------------------------------
// | Copyright (c) 2017-2020 http://suifeng.tech All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: suifeng <1787585212@qq.com>
// +----------------------------------------------------------------------

namespace suifeng\admin;

use suifeng\Controller;
use suifeng\admin\AdminMenu;
use suifeng\admin\AdminForm;
use suifeng\mvc\ModuleHelper;

abstract class AdminController extends Controller
{
//     /**
//      * 是否需要登录？
//      * 、
//      * @var boolean
//      */
//     protected $need_login = true;

    /**
     * 系统参数，页面间跳转时需要保留的参数。
     * 系统参数与保留参数的作用相同，
     * 只是系统参数在AdminController类中定义，
     * 保留参数在子类中定义，避免重复。
     *
     * @var array
     */
    protected $system_params = array('ids');

    /**
     * 保留参数，页面间跳转时需要保留的参数。
     * 系统参数与保留参数的作用相同，
     * 只是系统参数在AdminController类中定义，
     * 保留参数在子类中定义，避免重复。
     *
     * @var array
     */
    protected $reserve_params = array();

    /**
     * 条件参数，用于列表时作为查询条件的参数。
     *
     * @var array
     */
    protected $where_params = array();

    /**
     * 初始化控制器。
     */
    protected function _initialize()
    {
        //session('user_auth', array('uid' => 1, 'username' => 'admin'));

        /*
        // 当前请求地址
        $current_url = strtolower(request()->module() . '/' . request()->controller() . '/' . request()->action());

        // 用户登录和权限检查
        $not_login_urls = config('admin_not_login_urls'); // 不需要授权就能够访问的地址列表
        $not_login_urls[] = config('admin_login_url'); // 登录页
        if ($this->need_login && !in_array($current_url, $not_login_urls)) {
            // 检查是否有登录？
            if (! is_login()) {
                if (request()->isAjax()) {
                    $this->error('请先登录系统', url(config('admin_login_url'), '', true, true), array('login' => 1));
                } else {
                    $this->redirect(url(config('admin_login_url')));
                }
            }

            // 检查是否有权限？
            $not_auth_urls = config('admin_not_auth_urls'); // 不需要授权就能够访问的地址列表
            $not_auth_urls[] = config('admin_index_url'); // 首页不需要权限
            if (! in_array($current_url, $not_auth_urls)) {
                if (! model('admin/group')->checkMenuAuth()) {
                    $this->error('权限不足！', url(config('admin_login_url')));
                }
            }
        }
        */

        $x = is_login();
        $y = request()->url();

        // 检查用户是否登录，是否有权限。
        $this->_check_access_control();



/*
        $this->assign('_admin_tabs', config('admin_tabs'));

        // 获取所有导航
        $menu_list = model('admin/module')->getAllMenu();
        $this->assign('_menu_list', $menu_list); // 后台主菜单

        // 获取左侧导航
        if (!config('admin_tabs')) {
            $parent_menu_list = model('admin/module')->getParentMenu();
            if (isset($parent_menu_list[0]['top'])) {
                $current_menu_list = $menu_list[$parent_menu_list[0]['top']];
            } else if (isset($menu_list[request()->module()])) {
                $current_menu_list = $menu_list[request()->module()];
            } else {
                $current_menu_list = null;
            }
            $this->assign('_current_menu_list', $current_menu_list); // 后台左侧菜单
            $this->assign('_parent_menu_list', $parent_menu_list); // 后台父级菜单
        }
*/

    }

    protected function _check_access_control()
    {
        // 首先检查controller，再检查action。
        // 在满足controller定义的基础上，再检查是否满足action定义。

        // 检查controller有没有定义@Acces。
        $ref_class = new \ReflectionAnnotatedClass($this);
        if ($ref_class->hasAnnotation('Access')) {
            $class_access_anno = $ref_class->getAnnotation('Access');
            if (is_null($class_access_anno->login) || $class_access_anno->login === true) {
                if (is_login()) {
                    if ($this->_check_required_roles($class_access_anno->roles) !== true) {
                        if ($this->_check_required_permissions($class_access_anno->permissions) !== true) {
                            if (!empty($class_access_anno->roles) || !empty($class_access_anno->permissions)) {
                                $this->_process_access_denied();
                            }
                        }
                    }
                } else {
                    $this->_process_login_error();
                }
            }
        }

        // 检查action有没有定义@Acces。
        $ref_method = new \ReflectionAnnotatedMethod($this, request()->action());
        if ($ref_method->hasAnnotation('Access')) {
            $method_access_anno = $ref_method->getAnnotation('Access');
            if (is_null($method_access_anno->login) || $method_access_anno->login === true) {
                if (is_login()) {
                    if ($this->_check_required_roles($method_access_anno->roles) !== true) {
                        if ($this->_check_required_permissions($method_access_anno->permissions) !== true) {
                            if (!empty($method_access_anno->roles) || !empty($method_access_anno->permissions)) {
                                $this->_process_access_denied();
                            }
                        }
                    }
                } else {
                    $this->_process_login_error();
                }
            }
        }

        // 如果controller和action都没有定义，也是需要检查是否登录的。
        if (empty($class_access_anno) && empty($method_access_anno)) {
            if (!is_login()) {
                $this->_process_login_error();
            }
        }
    }

    protected function _check_required_roles($role_list)
    {
        foreach ((array) $role_list as $role_name) {
            if (true) {
                return true;
            }
        }
        return false;
    }

    protected function _check_required_permissions($permission_list)
    {
        foreach ((array) $permission_list as $permission_name) {
            if (model('admin/user')->has_permission($permission_name)) {
                return true;
            }
        }
        return false;
    }

    protected function _process_login_error()
    {
        if (request()->isAjax()) {
            $this->error('请先登录系统。', url('admin/login/index'));
        } else {
           $this->redirect(url('admin/login/index'));
        }
    }

    protected function _process_access_denied()
    {
        $this->error('无权限执行此操作。', url(config('admin_index_url')));
    }




//  protected function _check_access_annotation($annotation)
//  {
//      $login = boolval($annotation->login);
//      $role_list = (array) $annotation->roles;
//      $permission_list = (array) $annotation->permissions;

//      // 是否可以匿名访问？
//      if (!$login) {
//             return;
//         } else {
//             if (!is_login()) {
//                 if (request()->isAjax()) {
//                     $this->error('请先登录系统', url(config('admin_login_url'), '', true, true), array('login' => 1));
//                 } else {
//                     redirect(url(config('admin_login_url'), '', true, true));
//                 }
//             }
//         }

//         // 可以访问的角色？任意一个
//         if ($role_list) {
//             foreach ($role_list as $role_name) {
//                 if (true) {
//                     return;
//                 }
//             }
//         }

//         // 可以访问的权限？任意一个
//         if ($permission_list) {
//             foreach ($permission_list as $permission_name) {
//                 if (true) {
//                     return;
//                 }
//             }
//         }

//         // 如果角色和权限都为空，说明不需要特殊权限。
//         if (empty($role_list) && empty($permission_list)) {
//             return;
//         }

//         $this->error('无权限执行', url(config('admin_index_url')));
//  }

//  /**
//   * 检查是否需要登录。
//   */
//  protected function _check_need_login()
//  {
//      // 检查action有没有定义@Anonymous。
//      $ref_method = new \ReflectionAnnotatedMethod($this, request()->action());
//      if ($ref_method->hasAnnotation('Anonymous')) {
//          if ($this->_check_anonymous_annotation($ref_method->getAnnotation('Anonymous'))) {
//                 return false;
//          }       }

//      // 检查controller有没有定义@Anonymous。
//      $ref_class = new \ReflectionAnnotatedClass($this);
//      if ($ref_class->hasAnnotation('Anonymous')) {
//          if ($this->_check_anonymous_annotation($ref_class->getAnnotation('Anonymous'))) {
//              return false;
//          }
//      }

//      // 没有@Anonymous，或@@Anonymous(false)，就要检查登录。
//      if (is_login()) {
//          return true;
//      }

//         if (request()->isAjax()) {
//             $this->error('请先登录系统', url(config('admin_login_url'), '', true, true), array('login' => 1));
//         } else {
//             redirect(url(config('admin_login_url'), '', true, true));
//         }
//  }

//  protected function _check_need_permissions()
//  {
//      // 是否有定义注解？
//      $anno_defined = false;

//      // 检查action有没有定义相应注解。
//      $ref_method = new \ReflectionAnnotatedMethod($this, request()->action());
//      if ($ref_method->hasAnnotation('HasRoles')) {
//          if ($this->_check_role_annotation($ref_method->getAnnotation('HasRoles'))) {
//              return;
//          }
//          $anno_defined = true;
//      }
//      if ($ref_method->hasAnnotation('HasPermissions')) {
//          if ($this->_check_permission_annotation($ref_method->getAnnotation('HasPermissions'))) {
//              return;
//          }
//          $anno_defined = true;
//      }

//      // 检查controller有没有定义相应注解。
//      $ref_class = new \ReflectionAnnotatedClass($this);
//      if ($ref_class->hasAnnotation('HasRoles')) {
//          if ($this->_check_role_annotation($ref_class->getAnnotation('HasRoles'))) {
//              return;
//          }
//          $anno_defined = true;
//      }
//      if ($ref_class->hasAnnotation('HasPermissions')) {
//          if ($this->_check_permission_annotation($ref_class->getAnnotation('HasPermissions'))) {
//              return;
//          }
//          $anno_defined = true;
//      }

//      // 如果定义了注解，但是不满足条件，则返回错误。
//      // 如果没有定义注解，则说明不需要特殊权限，登录就可以。
//      if ($anno_defined) {
//          $this->error('无权限执行', url(config('admin_index_url')));
//      }
//  }

//  protected function _check_anonymous_annotation($annotation)
//  {
//      $value = $annotation->value;
//      $value = is_null($value) ? true : boolval($value);
//      return $value;
//  }

//  protected function _check_role_annotation($annotation)
//  {
//      $role_list = (array) $annotation->value;
//      foreach ($role_list as $role_name) {
//          if (true) {
//              return true;
//          }
//      }
//      return false;
//  }

//  protected function _check_permission_annotation($annotation)
//  {
//      $permission_list = (array) $annotation->value;
//      foreach ($permission_list as $permission_name) {
//          if (true) {
//              return true;
//          }
//      }
//      return false;
//  }

    /**
     * 模板显示。
     */
    protected function display($template = '', $vars = [], $replace = [], $config = [])
    {
//         $this->_admin_menu = service('admin/menu')->get_admin_menu_array();
//         service('admin/menu')->set_active_url($this->_admin_menu); // 调用这个方法，用引用的方式传递admin_menu，修改它的_active值。

//         $this->_admin_view = $this->view;// \suifeng\mvc\admin\AdminView();
//         $this->_admin_view->template = $template;
//         //$this->_admin_view->assign(\suifeng\helper\ClassHelper::get_property($this->view, 'data'));
//         $this->_admin_view->assign((array) $vars);
//         $this->_admin_view->assign('_admin_menu', $this->_admin_menu);
//         $this->_admin_view->assign('_module_menu', service('admin/menu')->get_module_menu($this->_admin_menu));
//         $this->_admin_view->assign('_user_auth', session('user_auth')); // 用户登录信息
//         $this->_admin_view->assign('_admin_layout', config('ADMIN_PUBLIC_LAYOUT')); // 页面公共继承模版
//         $this->_admin_view->assign('_page_name', strtolower(request()->module() . '-' . request()->controller() . '-' . request()->action() . '-page'));
//         $this->_admin_view->assign('_index_url', $this->url('index'));
//         $this->_admin_view->assign('_request_url', request()->url());
//         $this->_admin_view->assign('_controller', $this);
//         //$this->_admin_view->assign('_new_message', cookie('_new_message')); // 获取用户未读消息数量
//         $this->_populate_admin_view($this->_admin_view);

//         //$this->assign($this->_admin_view->tpl_vars);
//         $template = strtolower($this->_admin_view->template);

        if (request()->isAjax()) {
            $html = $this->fetch($template, $vars, $replace, $config);
            $this->success(null, null, array('html' => $html));
        } else {
            echo $this->fetch($template, $vars, $replace, $config);
        }
    }

    /**
     * 加载模板输出
     * @access protected
     * @param string $template 模板文件名
     * @param array  $vars     模板输出变量
     * @param array  $replace  模板替换
     * @param array  $config   模板参数
     * @return mixed
     */
    protected function fetch($template = '', $vars = [], $replace = [], $config = [])
    {
        if (empty($template)) {
            $depr = config('template.view_depr');
            $template = request()->controller() . $depr . request()->action();
        }
        $this->_populate_template_vars();
        return parent::fetch($template, $vars, $replace, $config);
    }

    protected function _populate_template_vars()
    {
        $admin_menu = new \suifeng\admin\AdminMenu();
        $this->assign('_controller', $this);
        $this->assign('_request_module', request()->module());
        $this->assign('_request_action', request()->action());
        $this->assign('_request_controller', request()->controller());
        $this->assign('_request_url', request()->url());
        $this->assign('_page_name', strtolower(request()->module() . '-' . request()->controller() . '-' . request()->action() . '-page'));
        $this->assign('_admin_layout', config('admin_layout_path'));

        $this->assign('_admin_menu', $admin_menu->get_menu_array());
        $this->assign('_module_menu', $admin_menu->get_module_menu());
        $this->assign('_breadcrumbs', $this->_get_breadcrumbs($admin_menu));
        $this->assign('_user_auth', session('user_auth'));
        $this->assign('_new_message', cookie('_new_message')); // 用户未读消息数量
        $this->assign('_admin_form', new \suifeng\admin\AdminForm());
        $this->assign('_admin_table', new \suifeng\admin\AdminTable());
        $this->assign('_admin_html', new \suifeng\admin\AdminHtml());
        $this->assign('_admin_toolbar', new \suifeng\admin\AdminToolbar());
        model('admin/module')->invoke_all_modules('admin_view', $this->view);
    }

    protected function _get_breadcrumbs($admin_menu)
    {
        $url = request()->module() . '/' .  request()->controller() . '/' . request()->action();
        if (($titleList = $admin_menu->field_list($url, 'title')) !== null) {
            return $titleList;
        }

        if (request()->action() <> 'index') {
            $url = request()->module() . '/' .  request()->controller() . '/index';
            $found = $admin_menu->find_by_url($url);
            if (($titleList = $admin_menu->field_list($url, 'title')) !== null) {
                //$titleList[] = $this->_get_view_var('title');
                return $titleList;
            }
        }

        return array();
    }






//     protected function _populate_admin_view($admin_view)
//     {
//         $method_prefix = '_fetch_view_';
//         foreach (get_class_methods($this) as $method_name) {
//             if (substr($method_name, 0, strlen($method_prefix)) == $method_prefix) {
//                 $var_name = substr($method_name, strlen($method_prefix));
//                 if (!isset($admin_view->$var_name)) {
//                     $method_return = call_user_func(array($this, $method_name));
//                     $admin_view->assign($var_name, $method_return);
//                 }
//             }
//         }

//         ModuleHelper::invokeMethod(null, 'admin_view', $admin_view);
//     }

//  protected function _get_admin_menu()
//  {
//      if (isset($this->_admin_menu)) {
//          return $this->_admin_menu;
//      }

//      $this->_admin_menu = ModuleHelper::getAdminMenu();
//      AdminMenu::setActiveUrl($this->_admin_menu); // 调用这个方法，用引用的方式传递admin_menu，修改它的_active值。
//      return $this->_admin_menu;
//  }

//  protected function _get_admin_view()
//  {
//      if (isset($this->_admin_view)) {
//          return $this->_admin_view;
//      }

//         $this->_admin_view = new \suifeng\mvc\admin\AdminView();
//         $this->_admin_view->assign(\suifeng\helper\ClassHelper::get_property($this->view, 'data'));

//         $method_prefix = '_admin_view_';
//         foreach (get_class_methods($this) as $method_name) {
//             if (substr($method_name, 0, strlen($method_prefix)) == $method_prefix) {
//                 $var_name = substr($method_name, strlen($method_prefix));
//                 if (!isset($this->_admin_view->tpl_vars[$var_name])) {
//                     $method_return = call_user_func(array($this, $method_name));
//                     $this->_admin_view->assign($var_name, $method_return);
//                 }
//             }
//         }

//         ModuleHelper::invokeMethod(null, 'admin_view', $this->_admin_view);
//      return $this->_admin_view;
//  }

//     protected function _get_view_var($name)
//     {
//         if (isset($this->_admin_view->$name)) {
//             return $this->_admin_view->$name;
//         }

//         $method_name = '_fetch_view_' . $name;
//         if (method_exists($this, $method_name)) {
//             $method_return = call_user_func(array($this, $method_name));
//             $this->_admin_view->assign($name, $method_return);
//             return $method_return;
//         }

//         return null;
//     }

//     protected function _fetch_view_title()
//     {
//         $ref_method = new \ReflectionAnnotatedMethod($this, request()->action());
//         if ($ref_method->hasAnnotation('Title')) {
//             return $ref_method->getAnnotation('Title')->value;
//         }

//         if (request()->action() == 'index') {
//             $ref_class = new \ReflectionAnnotatedClass($this);
//             if ($ref_class->hasAnnotation('Title')) {
//                 return $ref_class->getAnnotation('Title')->value;
//             }
//         }

//         $url = request()->module() . '/' .  request()->controller() . '/' . request()->action();
//         $found = service('admin/menu')->find_by_url($this->_admin_menu, $url);
//         if ($found && isset($found['title'])) {
//             return $found['title'];
//         }

//         return strtoupper(request()->action());
//     }

//     protected function _fetch_view_page_title()
//     {
//         return $this->_get_view_var('title');
//     }

    protected function _get_pagination()
    {
        $list_info['page_num'] = input('page', 1);
        $list_info['page_size'] = input('size', config('ADMIN_PAGE_ROWS'));
        $list_info['sort_field'] = input('sort');
        $list_info['sort_order'] = input('order');
        $list_info['selected'] = (array)input('ids/a');

        $list_info['where_map'] = array();
        $input = request()->param();

        foreach ($this->where_params as $key) {
            if (array_key_exists($key, $input)) {
                $list_info['where_map'][$key] = $input[$key];
            }
        }

        return $list_info;
    }

//     protected function _get_list_params()
//     {
//         $page = input('page', 1);
//         $size = input('size', config('ADMIN_PAGE_ROWS'));
//         $sort = input('sort');
//         $order = input('order');

//         $where = array();
//         $input = request()->param();

//         foreach ($this->where_params as $key) {
//             if (array_key_exists($key, $input)) {
//                 $where[$key] = $input[$key];
//             }
//         }

//         return array($where, $page, $size, $sort, $order);
//     }

    public function url($action, $args = array())
    {
        $input = request()->param();
        $params = array_merge(
            $this->system_params,
            $this->reserve_params,
            $this->where_params,
            array('page', 'size', 'sort', 'order'));

        foreach ($params as $key) {
            if (array_key_exists($key, $input) && !array_key_exists($key, $args)) {
                $args[$key] = $input[$key];
            }
        }

        return url($action, $args);
    }

    protected function post_array()
    {
        return AdminForm::handle_post();
    }

    protected function post_value($key)
    {
        $array = $this->post_array();
        if (array_key_exists($key, $array)) {
            return $array[$key];
        } else {
            return null;
        }
    }
}

